package cn.taobaoke.restful.service;

import cn.taobaoke.restful.domain.*;
import cn.taobaoke.restful.exception.TBKException;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

/**
 * @author yangzuo
 * @since 2017-03-21
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WxGroupService {

    //注意 members 字段的处理。 有则: 1) 创建或更新用户信息 2) 旧关闭不存在时,创建新关系
    public void createOrUpdateGroupAndMembers(WxGroupEntity wxGroupEntity, final Long domainId) {
        val dbGroupOpt = wxGroupRepository.findFirstByNameAndDomainId(wxGroupEntity.getName(), domainId);

//        WxGroupEntity dbGroup = null;
//        if (! dbGroupOpt.isPresent()) {
//            // 新用户时候, 则创建, 以及所有的关系链
//            wxGroupEntity.setDomainId(domainId);
//            dbGroup = wxGroupRepository.save(wxGroupEntity);
//        } else {
//            dbGroup = dbGroupOpt.get();
//        }

        WxGroupEntity dbGroup = dbGroupOpt.orElseGet(() -> {
            wxGroupEntity.setDomainId(domainId);
            return wxGroupRepository.save(wxGroupEntity);
        });

        if (wxGroupEntity.getMembers() != null) {
            dbGroup.setMembers(wxGroupEntity.getMembers());
        }

        // 用户信息处理
        List<UserEntity> members = userService.createUserIfNameNotExist(dbGroup.getMembers(), domainId);

        // 群 - 用户关系处理
        if (members == null || members.isEmpty()) return;

//        List<Long> userIds = members.stream().map(user -> user.getId()).collect(Collectors.toList());
        val userIds = new ArrayList<Long>(members.size());
        for (UserEntity member : members) {
            userIds.add(member.getId());
        }

        val relations = userGroupRelationRepository.findByDomainIdAndGroupIdAndUserIdIn(domainId, dbGroup.getId(), userIds);
        val existIds = new HashSet<Long>();
        if (relations != null && relations.size() > 0) {
            relations.forEach(relation -> existIds.add(relation.getUserId()));
        }

        val notExistRelations = new ArrayList<UserGroupRelation>(members.size());
        for (UserEntity member : members) {
            if (existIds.contains(member.getId())) {
                continue;
            }

            val userGroupRelation = new UserGroupRelation();
            userGroupRelation.setGroupId(dbGroup.getId());
            userGroupRelation.setUserId(member.getId());
            userGroupRelation.setDomainId(domainId); // domainId
            notExistRelations.add(userGroupRelation);
        }

        userGroupRelationRepository.saveAll(notExistRelations);
    }

    /**
     * 为代理查询微信组
     */
    public WxGroupEntity getWxGroupByIdForAgent(final Long groupId, final Long agentId, final Long domainId) {
        val relationOpt = agentGroupRelationRepository.findByAgentIdAndGroupIdAndDomainId(agentId, groupId, domainId);
        if (relationOpt.isPresent()) {
            val wxGroupEntityOpt = wxGroupRepository.findByGroupId(groupId, false, domainId);
            return wxGroupEntityOpt.orElse(null);
        }
        return null;
    }

    /**
     * 为管理员查询微信组
     */
    public WxGroupEntity getWxGroupByIdForAdmin(final Long groupId, final Long domainId) {
        val opt = wxGroupRepository.findByGroupId(groupId, true, domainId);
        return opt.orElse(null);
    }

    /**
     * 为管理员查询微信组列表
     */
    public List<WxGroupEntity> getWxGroupListForAdmin(final Long domainId) {
        List<WxGroupEntity> groups = wxGroupRepository.findAllByDomainId(domainId);
        return addGroupOwner(groups, domainId);
    }

    /**
     * 为代理查询微信组列表
     */
    public List<WxGroupEntity> getWxGroupListForAgent(final Long agentId, final Long domainId) {
        List<WxGroupEntity> groups = wxGroupRepository.findWxGroupListByAgentId(agentId, domainId);
        return addGroupOwner(groups, domainId);
    }

    private List<WxGroupEntity> addGroupOwner(final List<WxGroupEntity> groups, final Long domainId) {
        if (groups == null || groups.isEmpty()) return groups;

        List<Long> agentIds = new ArrayList<>(groups.size());
        for (WxGroupEntity group : groups) {
            if (group.getAgentId() != null) {
                agentIds.add(group.getAgentId());
            }
        }

        if (agentIds.isEmpty()) return groups;

        List<AgentEntity> agents = agentRepository.findByIdIn(agentIds, domainId);
        for (WxGroupEntity group : groups) {
            Long agentId = group.getAgentId();
            if (agentId != null) {
                for (AgentEntity agent : agents) {
                    if (agentId.longValue() == agent.getId().longValue()) {
                        group.setAgent(agent);
                        break;
                    }
                }
            }
        }
        return groups;
    }

    /**
     * 根据微信组查询PID
     */
    public Map getPidListForWxGroups(final List<String> groupList, final Long domainId) {
        Map<String, String> pidMaps = new HashMap<>();
        for (String groupName : groupList) {
            groupName = clearGroupName(groupName);
            String pid = queryPidForWxGroup(groupName, domainId);
            pidMaps.put(groupName, pid);
        }
        return pidMaps;
    }

    public String clearGroupName(String groupName) {
        try {
            return URLDecoder.decode(groupName, "utf-8");
        } catch (UnsupportedEncodingException e) {
            logger.error("parse encode failed!",e);
            return groupName;
        }
    }

    public String queryPidForWxGroup(final String wxGroupName, final Long domainId) {
        val resultOpt = wxGroupRepository.findWxGroupPidByName(wxGroupName, domainId);

        String pid = resultOpt
                .orElseGet(() -> pidService.getOrCreateAdminPid(domainId).getPid());

        logger.info("get wxGroupName => {} pid failed, return admin pid => {}", wxGroupName, pid);
        return pid;
    }


    // TODO 需要修改

    /**
     * @param groupId
     * @param agentId
     * @return
     */
    public WxGroupEntity checkWxGroupExistForAgent(final Long groupId, final Long agentId, final Long domainId) {
        val entityOpt = wxGroupRepository.findGroupForAgentByAgentIdAndGroupId(agentId, groupId, domainId);
        if (! entityOpt.isPresent()) {
            logger.error("代理[{}]的微信群[{}]不存在", agentId, groupId);
            throw new TBKException("代理[" + agentId + "]微信群[" + groupId + "]不存在");
        }
        return entityOpt.get();
    }

    /**
     * @param groupId
     * @return
     */
    public WxGroupEntity checkWxGroupExistForAdmin(final Long groupId, final Long domainId) {
        val entityOpt = wxGroupRepository.findByIdAndIsBelongToAdminAndDomainId(groupId, true, domainId);
        if (! entityOpt.isPresent()) {
            logger.error("管理员的微信群[{}]不存在", groupId);
            throw new TBKException("管理员微信群[" + groupId + "]不存在");
        }
        return entityOpt.get();
    }

    /**
     * 添加微信群信息
     */
    public WxGroupEntity addWxGroupEntity(final WxGroupEntity wxGroupEntity, final Boolean isAdmin, final Long domainId) {
        val entityOpt = wxGroupRepository.findByName(wxGroupEntity.getName(), isAdmin, domainId);
        if (entityOpt.isPresent()) {
            return entityOpt.get();
        }

        wxGroupEntity.setId(null);
        wxGroupEntity.setIsBelongToAdmin(isAdmin);
        wxGroupEntity.setDomainId(domainId);
        return wxGroupRepository.save(wxGroupEntity);
    }

    public Long getAgentIdByGroupName(String group, Long domainId) {
        val dbGroupOpt = wxGroupRepository.findFirstByNameAndDomainId(group, domainId);
        if (dbGroupOpt.isPresent()) {
            return dbGroupOpt.get().getAgentId();
        }
        return null;
    }





    private final @NonNull PIDService pidService;

    private final @NonNull WxGroupRepository wxGroupRepository;

    private final @NonNull AgentRepository agentRepository;

    private final @NonNull UserService userService;

    private final @NonNull AgentGroupRelationRepository agentGroupRelationRepository;

    private final @NonNull UserGroupRelationRepository userGroupRelationRepository;

    private final @NonNull GlobalConfigService globalConfigService;

    private static Logger logger = LogManager.getLogger(WxGroupService.class);
}
